#include "UsrAI.h"
#include <set>
#include <cmath>
#include <iostream>
#include <unordered_map>
#include <mutex>
using namespace std;
tagGame tagUsrGame;
ins UsrIns;
tagInfo info;
static int stage = 0;
char Map[130][130]{};
int MAP[130][130]{};
int center_x;
int center_y;
int target_x = -1;
int target_y = -1;
int shore_x = -1;
int shore_y = -1;
int grass_x = -1;
int grass_y = -1;
int first_x = -1;
int first_y = -1;
int stable_x = -1;
int stable_y = -1;
int house_N = 0;
int dock_N = 0;
int fishingBoat_N = 0;
int wareHouse_N = 0;
int granary_N = 0;
int market_N = 0;
int ship_N = 0;
int boat_N = 0;
int farm_N = 0;
int farmer_N = 4;
int armyCamp_N = 0;
int clubMan_N = 0;
int stable_N = 0;
int scout_N = 0;
int cancle_N = 0;
int range_N = 0;
int bowMan_N = 0;
int farmer_cnt = 0;
int newFarmer_cnt = 0;
int arrowTower_N = 0;
int gold_cnt = 0;
int enemy_cnt = 0;
double size = sqrt(1280);
bool is_upgradeCutting = false;
bool is_upgradeStone = false;
bool is_upgradeGold = false;
bool is_upgradeFarm = false;
bool is_upgradeTool = false;
bool is_upgradeInfantry = false;
bool is_upgradeArcher = false;
bool is_upgradeRider = false;
bool is_upgradeClubMan = false;
bool is_researchArrowTower = false;
bool is_arrived = false;
bool findEnemy = false;
bool findNewContinent = false;
bool findNewEnemy = false;
bool findGold = false;
bool findFirst = false;
bool findFirstShip = false;
bool findNewShore = false;
bool findScout = false;
unordered_set<int> livingResources;
set<pair<int, int>> newContinent;
set<pair<int, int>> newSea;
unordered_map<int, int> cntResources;
unordered_map<int, tagBuilding> buildings;
unordered_map<int, tagResource> resources;
unordered_map<int, tagFarmer> farmers;
unordered_map<int, pair<int,int>> boats;
unordered_map<int, int> ships;
unordered_map<int, bool> boatFirstMove;
unordered_map<int, bool> boatMove;
unordered_map<int, bool> boatBack;
unordered_map<int, bool> farmerMove;
unordered_map<int, int> farmerOnBoat;
vector<pair<int, int>> exploreArea = {{32, 32}, {32, 64}, {32, 96}, {64, 32}, {64, 64}, {64, 96}, {96, 32}, {96, 64}, {96, 96}};
vector<bool> is_visited(9, false);
const int dx[] = {1, -1, 0, 0, 1, 1, -1, -1};
const int dy[] = {0, 0, 1, -1, 1, -1, 1, -1};
const int ddx[] = {-1, 0, 1, 2, 2, 2, 2, 1, 0, -1, -1, -1};
const int ddy[] = {-1, -1, -1, -1, 0, 1, 2, 2, 2, 2, 1, 0};
void UsrAI::init(){
    for(auto& building : info.buildings){
        if(building.Type == BUILDING_CENTER){
            center_x = building.BlockDR + 1;
            center_y = building.BlockUR + 1;
            break;
        }
    }
}
void UsrAI::updateMap(){
    if(!findNewShore && findFirst && findNearbyWater(stable_x, stable_y, shore_x, shore_y) ){
        findNewShore = true;
        findGrassSpace(shore_x, shore_y, grass_x, grass_y);
    }

    if(target_x != -1 && target_y != -1) MAP[target_x][target_y] = '*';
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if((*info.theMap)[i][j].type == MAPPATTERN_UNKNOWN) Map[i][j] = '?';
            else if((*info.theMap)[i][j].type == MAPPATTERN_OCEAN){
                if(Map[i][j] == '?'){
                    newSea.emplace(i, j);
//                    if(feasibleWater(i, j) && !findNewShore && findFirst
//                            && distance(i, j, armyCamp_x, armyCamp_y) > 35
//                            && distance(i, j, armyCamp_x, armyCamp_y) < 40
//                            && distance(armyCamp_x, armyCamp_y, i, j) > distance(first_x, first_y, i, j)){
//                        findNewShore = true;
//                        shore_x = i;
//                        shore_y = j;
//                        findGrassSpace(shore_x, shore_y, grass_x, grass_y);
//                    }
                }
                 Map[i][j] = '-';
            }
            else if((*info.theMap)[i][j].type == MAPPATTERN_GRASS){
                if(Map[i][j] == '?'){
                    findNewContinent = true;
                    newContinent.emplace(i, j);
                }
                 Map[i][j] = (*info.theMap)[i][j].height + '0';
            }
        }
    }
    for(int i = 0;  i < 128; i++){
        for(int j = 0; j < 128; j++){
            MAP[i][j] = 0;
            if((*info.theMap)[i][j].type != MAPPATTERN_GRASS) continue;
            for(int k = 0; k < 8; k++){
                int x = i + dx[k];
                int y = j + dy[k];
                if(x < 0 || x > 128 || y < 0 || y > 128 || (*info.theMap)[x][y].type != MAPPATTERN_GRASS) continue;
                if((*info.theMap)[i][j].height != (*info.theMap)[x][y].height){
                    Map[i][j] = '/';
                    break;
                }
            }
        }
    }
    findGold = false;
    gold_cnt = 0;
    for(auto& resource : info.resources){
        if(resource.Type == RESOURCE_GOLD) findGold = true, gold_cnt++;
        if(resource.Type == RESOURCE_FISH || resource.Type == RESOURCE_STONE || resource.Type == RESOURCE_GOLD){
            for(int i = 0; i < 2; i++){
                for(int j = 0; j < 2; j++){
                    MAP[resource.BlockDR + i][resource.BlockUR + j] = resource.Type + 'A';
                }
            }
        }
        MAP[resource.BlockDR][resource.BlockUR] = resource.Type + 'A';
        resources[resource.SN] = resource;
    }
    house_N = 0;
    wareHouse_N = -1;
    armyCamp_N = 0;
    stable_N = 0;
    range_N = 0;
    granary_N = 0;
    market_N = 0;
    arrowTower_N = 0;
    farm_N = 0;
    dock_N = 0;
    for(auto& building : info.buildings){
        if(building.Type == BUILDING_HOME) house_N++;
        if(building.Type == BUILDING_STOCK) wareHouse_N++;
        if(building.Type == BUILDING_ARMYCAMP) armyCamp_N++;
        if(building.Type == BUILDING_STABLE){
            stable_N++;
            if(stable_x == -1 && stable_y == -1){
                stable_x = building.BlockDR;
                stable_y = building.BlockUR;
            }
        }
        if(building.Type == BUILDING_RANGE) range_N++;
        if(building.Type == BUILDING_GRANARY) granary_N++;
        if(building.Type == BUILDING_MARKET) market_N++;
        if(building.Type == BUILDING_ARROWTOWER) arrowTower_N++;
        if(building.Type == BUILDING_FARM) farm_N++;
        if(building.Type == BUILDING_DOCK) dock_N++;
        if(building.Type == BUILDING_HOME || building.Type == BUILDING_ARROWTOWER || building.Type == BUILDING_DOCK){
            for(int i = 0; i < 2; i++){
                for(int j = 0; j < 2; j++){
                    MAP[building.BlockDR + i][building.BlockUR + j] = building.Type + 'a';
                }
            }
        }else{
            for(int i = 0; i < 3; i++){
                for(int j = 0; j < 3; j++){
                    MAP[building.BlockDR + i][building.BlockUR + j] = building.Type + 'a';
                }
            }
        }
        buildings[building.SN] = building;
    }
    farmer_cnt = 0;
    newFarmer_cnt = 0;
    fishingBoat_N = 0;
    farmerOnBoat.clear();
    for(auto& farmer : info.farmers){
        farmers[farmer.SN] = farmer;
        MAP[farmer.BlockDR][farmer.BlockUR] = '*';
        if(farmer.FarmerSort == 0){
            if(newContinent.count({farmer.BlockDR, farmer.BlockUR})) newFarmer_cnt++;
            else farmer_cnt++;
            farmerOnBoat[farmer.WorkObjectSN]++;
        }
        if(farmer.FarmerSort == 1) farmerOnBoat[farmer.SN] += farmer.Resource;
        if(farmer.FarmerSort == 2) fishingBoat_N++;
    }
    ship_N = 0;
    clubMan_N = 0;
    scout_N = 0;
    bowMan_N = 0;
    for(auto& army : info.armies){
        if(army.Sort == AT_SHIP){
             ship_N++;
//             for(int i = -1; i <= 1; i++){
//                 for(int j = -1; j <= 1; j++){
//                     int x = army.BlockDR + i;
//                     int y = army.BlockUR + j;
//                     if(x >= 0 && x < 128 && y >= 0 && y < 128){
//                         MAP[x][y] = '*';
//                     }
//                 }
//             }
        }
        if(army.Sort == AT_CLUBMAN) clubMan_N++;
        if(army.Sort == AT_SCOUT) scout_N++;
        if(army.Sort == AT_BOWMAN) bowMan_N++;
        MAP[army.BlockDR][army.BlockUR] = '*';
    }
    findNewEnemy = false;
    findEnemy = false;
    enemy_cnt = 0;
    for(auto& enemy_building : info.enemy_buildings){
        findNewEnemy = true;
        for(int i = 0; i < 2; i++){
            for(int j = 0; j < 2; j++){
                MAP[enemy_building.BlockDR + i][enemy_building.BlockUR + j] = '*';
            }
        }
    }
    for(auto& enemy_army : info.enemy_armies){
        findEnemy = true;
        if(enemy_army.Sort == AT_SCOUT) findScout = true;
        if(enemy_army.Sort != AT_SHIP){
            if(!findFirst){
                first_x = enemy_army.BlockDR, first_y = enemy_army.BlockUR;
            }
            findEnemy = findNewEnemy = findFirst = true, enemy_cnt++;
        }
        else{
             findFirstShip = true;
             if(enemy_army.NowState == HUMAN_STATE_ATTACKING) findEnemy = true;
        }
        MAP[enemy_army.BlockDR][enemy_army.BlockUR] = '*';
    }
    for(int i = 0; i < 9; i++){
        int x = exploreArea[i].first;
        int y = exploreArea[i].second;
        if(Map[x][y] != '?'){
            is_visited[i] = true;
        }
    }
}
double UsrAI::distance(int a, int b, int c, int d){
    return sqrt(pow(a - c, 2) + pow(b - d, 2));
}
bool UsrAI::cutTree(int op){
    tagFarmer idleFarmer;
    tagResource targetTree;
    if(op == 0){
        if(findIdleFarmer(idleFarmer, 0) == false) return false;
    }else{
        if(findIdleFarmer(idleFarmer) == false) return false;
    }
    if(findNearbyResource(idleFarmer.BlockDR, idleFarmer.BlockUR, targetTree, RESOURCE_TREE, 1) == false) return false;
    if(op == 1 && !newContinent.count({targetTree.BlockDR, targetTree.BlockUR})){
        double x, y;
        if(findNearbyUnknown(idleFarmer.BlockDR, idleFarmer.BlockUR, x, y) == false) return false;
        HumanMove(idleFarmer.SN, x * size + 15, y * size + 15);
        return true;
    }
    HumanAction(idleFarmer.SN, targetTree.SN);
    return true;
}
bool UsrAI::digStone(){
    if(info.Stone >= 450) return false;
    if(findHumanWorkingOnSomething(0, RESOURCE_STONE) >= 2) return false;
    tagFarmer idleFarmer;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    tagResource stone;
    if(findNearbyResource(idleFarmer.BlockDR, idleFarmer.BlockUR, stone, RESOURCE_STONE, 1) == false) return false;
    HumanAction(idleFarmer.SN, stone.SN);
    return true;
}
bool UsrAI::digGold(){
    tagFarmer idleFarmer;
    if(findFarmer(idleFarmer, 1) == false) return false;
    tagResource gold;
    tagBuilding stock;
    if(gold_cnt <= 5 && findNearbyResource(idleFarmer.BlockDR, idleFarmer.BlockUR, gold, RESOURCE_GOLD, 0) == false) return false;
    if(gold_cnt > 5 && findNearbyGold(gold) == false) return false;
    findBuilding(gold.BlockDR, gold.BlockUR, BUILDING_STOCK, stock);
    if(distance(stock.BlockDR, stock.BlockUR, gold.BlockDR, gold.BlockUR) > 15){
        if(buildWareHouse(gold.BlockDR, gold.BlockUR, 1)) return true;
        return false;
    }else if(stock.Percent < 100 && findHumanWorkingOnSomething(stock.SN) < 2){
        HumanAction(idleFarmer.SN, stock.SN);
        return true;
    }
    HumanAction(idleFarmer.SN, gold.SN);
    return true;
}
bool UsrAI::findAvailableSpace(int center_x, int center_y, int& x, int& y, int k, int kk){
    int min_distance = INT_MAX;
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if(feasibleHouseSpace(i, j, k)){
                int nx, ny;
                findGrassSpace(i + 1, j + 1, nx, ny);
                if(distance(i + 1, j + 1, nx, ny) <= 4) continue;
                int cur_distance = abs(center_x - i) + abs(center_y - j);
                if(cur_distance >= kk && cur_distance < min_distance){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findFarmer(tagFarmer& idleFarmer, int op){
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && newContinent.count({farmer.BlockDR, farmer.BlockUR}) == op &&
                (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WORKING
                 && (resources[farmer.WorkObjectSN].Type == RESOURCE_TREE))){
            idleFarmer = farmer;
            return true;
        }
    }
    return false;
}
bool UsrAI::findIdleFarmer(tagFarmer& idleFarmer, int num){
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == num && farmer.NowState == HUMAN_STATE_IDLE){
            if(newContinent.count({farmer.BlockDR, farmer.BlockUR})) continue;
            idleFarmer = farmer;
            return true;
        }
    }
    return false;
}
bool UsrAI::findIdleFarmer(tagFarmer& idleFarmer){
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE && newContinent.count({farmer.BlockDR, farmer.BlockUR})){
            idleFarmer = farmer;
            return true;
        }
    }
    return false;
}
bool UsrAI::findIdleBoat(tagFarmer& idleBoat){
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 1 && (farmer_cnt > 10 || newFarmer_cnt < 15 || farmerOnBoat[farmer.SN] > 0)
                && (farmerOnBoat[farmer.SN] < 5 || farmer.Resource < 5)){
            idleBoat = farmer;
            return true;
        }
    }
    return false;
}
bool UsrAI::findFullBoat(tagFarmer& fullBoat){
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 1 && (farmer.Resource == 5)){
            fullBoat = farmer;
            return true;
        }
    }
    return false;
}
bool UsrAI::findIdleArmy(tagArmy& idleArmy, int num){
    for(auto& army : info.armies){
        if(army.Sort == num && army.NowState == HUMAN_STATE_IDLE){
            idleArmy = army;
            return true;
        }
    }
    return false;
}
bool UsrAI::findSomeFarmers(vector<tagFarmer> & idleFarmers, int n, int num){
    idleFarmers.clear();
    for(auto& farmer : info.farmers){
        if(idleFarmers.size() == n) break;
        if(farmer.FarmerSort == num && farmer.NowState == HUMAN_STATE_IDLE){
            idleFarmers.push_back(farmer);
        }
    }
    return idleFarmers.size() == n;
}
bool UsrAI::findSomeFarmers(vector<int> & idleFarmers, int n, int num, int op){
    idleFarmers.clear();
    for(auto& farmer : info.farmers){
        if(idleFarmers.size() == n) break;
        if(farmer.FarmerSort == num && farmer.NowState == HUMAN_STATE_IDLE && newContinent.count({farmer.BlockDR, farmer.BlockUR}) == op){
            idleFarmers.push_back(farmer.SN);
        }
    }
    return idleFarmers.size() == n;
}
bool UsrAI::findNearbyFarmer(int center_x, int center_y, tagFarmer& targetFarmer, int k){
    int min_distance = INT_MAX;
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_IDLE){
            int cur_distance = abs(center_x - farmer.BlockDR) + abs(center_y - farmer.BlockUR);
            if(cur_distance < min_distance && cur_distance < k){
                targetFarmer = farmer;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyArea(int center_x, int center_y, int& x, int& y, int& k){
    int min_distance = INT_MAX;
    for(int i = 0; i < 9; i++){
        if(is_visited[i]) continue;
        int cur_x = exploreArea[i].first;
        int cur_y = exploreArea[i].second;
        int cur_distance = abs(center_x - cur_x) + abs(center_y - cur_y);
        if(cur_distance < min_distance){
            x = cur_x, y = cur_y, k = i;
            min_distance = cur_distance;
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyArmy(int center_x, int center_y, tagArmy& targetArmy, int num){
    int min_distance = INT_MAX;
    for(auto& army : info.armies){
        if(army.Sort == num){
            int cur_distance = abs(center_x - army.BlockDR) + abs(center_y - army.BlockUR);
            if(cur_distance < min_distance){
                targetArmy = army;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyEnemy(int center_x, int center_y, tagArmy& targetEnemy, int num){
    int min_distance = INT_MAX;
    for(auto& enemy : info.enemy_armies){
        if(enemy.Sort == num){
            if(num == AT_SHIP && enemy.NowState == HUMAN_STATE_WALKING) continue;
            int cur_distance = abs(center_x - enemy.BlockDR) + abs(center_y - enemy.BlockUR);
            if(cur_distance < min_distance){
                targetEnemy = enemy;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyEnemy(int center_x, int center_y, tagArmy& targetEnemy){
    int min_distance = INT_MAX;
    for(auto& enemy : info.enemy_armies){
        int cur_distance = abs(center_x - enemy.BlockDR) + abs(center_y - enemy.BlockUR);
        if(cur_distance < min_distance){
            targetEnemy = enemy;
            min_distance = cur_distance;
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyEnemyBuilding(int center_x, int center_y, tagBuilding& targetEnemy){
    int min_distance = INT_MAX;
    for(auto& enemy : info.enemy_buildings){
        int cur_distance = abs(center_x - enemy.BlockDR) + abs(center_y - enemy.BlockUR);
        if(cur_distance < min_distance){
            targetEnemy = enemy;
            min_distance = cur_distance;
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyResource(int center_x, int center_y, tagResource& target, int num, int op){
    double min_distance = INT_MAX;
    for(auto& resource : info.resources){
        if(resource.Type == num){
            if(op == 1 && findHumanWorkingOnResource(resource.SN) >= 2) continue;
            double cur_distance = pow(center_x - resource.BlockDR, 2) + pow(center_y - resource.BlockUR, 2);
            if(cur_distance < min_distance){
                target= resource;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyLivingResource(int center_x, int center_y, tagResource& target, int num){
    int min_distance = INT_MAX;
    for(auto& resource : info.resources){
        if(resource.Type == num && livingResources.count(resource.SN) == 0 && resource.Blood > 0){
            int cur_distance = abs(center_x - resource.BlockDR) + abs(center_y - resource.BlockUR);
            if(cur_distance < min_distance){
                target= resource;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyContinent(int center_x, int center_y, double& x, double& y){
    int min_distance = INT_MAX;
    for(pair<int, int> cur : newContinent){
        int i = cur.first, j = cur.second;
        if(!feasibleGrass(i, j)) continue;
        int cur_distance = abs(center_x - i) + abs(center_y - j);
        if(cur_distance < min_distance){
            x = i, y = j;
            min_distance = cur_distance;
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyUnknown(int center_x, int center_y, double& x, double& y){
    int min_distance = INT_MAX;
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if(feasibleArea(i, j)){
                int cur_distance = abs(center_x - i) + abs(center_y - j);
                if(cur_distance < min_distance){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyUnknownSea(int center_x, int center_y, int& x, int& y){
    int min_distance = INT_MAX;
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if(feasibleSea(i, j)){
                int cur_distance = abs(center_x - i) + abs(center_y - j);
                if(cur_distance < min_distance){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyBuilding(int center_x, int center_y, int target, tagBuilding& found){
    double min_distance = INT_MAX;
    for(auto& building : info.buildings){
        if(building.Project == 0 && building.Percent == 100 && building.Type == target){
            double cur_distance = pow(center_x - building.BlockDR, 2) + pow(center_y - building.BlockUR, 2);
            if(cur_distance < min_distance){
                found = building;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findNearbyGold(tagResource& gold){
    int max_cnt = -1, cnt = 0;
    tagBuilding stock;
    for(auto& resource : info.resources){
        if(resource.Type == RESOURCE_GOLD && feasibleGold(resource, cnt) && cnt > max_cnt){
            findBuilding(resource.BlockDR, resource.BlockUR, BUILDING_STOCK, stock);
            gold = resource;
            max_cnt = cnt;
        }
    }
    return max_cnt != -1;
}
bool UsrAI::findNearbyWater(int center_x, int center_y, int& x, int& y){
    double min_distance = INT_MAX;
    for(pair<int, int> cur : newSea){
        int i = cur.first, j = cur.second;
        if(!feasibleWater(i, j)
//                || distance(i, j, center_x, center_y) < distance(i, j, first_x, first_y)
                || distance(i, j, center_x, center_y) > 30) continue;
        double cur_distance = distance(i, j, center_x, center_y) + distance(i, j, first_x, first_y);
        if(cur_distance < min_distance){
            x = i, y = j;
            min_distance = cur_distance;
        }
    }
    return min_distance != INT_MAX;
}
bool UsrAI::findBuilding(int center_x, int center_y, int target, tagBuilding& found){
    double min_distance = INT_MAX;
    for(auto& building : info.buildings){
        if(building.Type == target){
            double cur_distance = pow(center_x - building.BlockDR, 2) + pow(center_y - building.BlockUR, 2);
            if(cur_distance < min_distance){
                found = building;
                min_distance = cur_distance;
            }
        }
    }
    return min_distance != INT_MAX;
}
int  UsrAI::findHumanWorkingOnSomething(int sort, int num){
    int cnt = 0;
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == sort && farmer.NowState == HUMAN_STATE_WORKING && resources[farmer.WorkObjectSN].Type == num){
            cnt++;
        }
    }
    return cnt;
}
int  UsrAI::findHumanWorkingOnSomething(int target){
    int cnt = 0;
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_WORKING && buildings[farmer.WorkObjectSN].SN == target){
            cnt++;
        }
    }
    return cnt;
}
int  UsrAI::findHumanWorkingOnResource(int target){
    int cnt = 0;
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_WORKING && resources[farmer.WorkObjectSN].SN == target){
            cnt++;
        }
    }
    return cnt;
}
bool UsrAI::feasibleHouseSpace(int x, int y, int k){
    if(x < 0 || x + k >= 129 || y < 0 || y + k >= 129) return false;
    if(MAP[x][y] != 0 || Map[x][y] == '?' || Map[x][y] == '-' || Map[x][y] == '/') return false;
    int height = Map[x][y];
    for(int i = 0; i < k; i++){
        for(int j = 0; j < k; j++){
            if(!feasibleHeight(x + i, y + j) || MAP[x + i][y + j] != 0 || Map[x + i][y + j] != height) return false;
        }
    }
    return true;
}
bool UsrAI::feasibleWaterSpace(int x, int y){
    if(newSea.count({x, y})) return false;
    if((*info.theMap)[x][y].type != MAPPATTERN_OCEAN || (*info.theMap)[x + 1][y].type != MAPPATTERN_OCEAN
            || (*info.theMap)[x][y + 1].type != MAPPATTERN_OCEAN || (*info.theMap)[x + 1][y + 1].type != MAPPATTERN_OCEAN) return false;
    if(MAP[x][y] != 0 || MAP[x + 1][y] != 0 || MAP[x][y + 1] != 0 || MAP[x + 1][y + 1] != 0) return false;
    if(x - 1 >= 0 && (*info.theMap)[x - 1][y].type == MAPPATTERN_GRASS && (*info.theMap)[x - 1][y + 1].type == MAPPATTERN_GRASS) return true;
    if(y - 1 >= 0 && (*info.theMap)[x][y - 1].type == MAPPATTERN_GRASS && (*info.theMap)[x + 1][y - 1].type == MAPPATTERN_GRASS) return true;
    if(x + 2 < 128 && (*info.theMap)[x + 2][y].type == MAPPATTERN_GRASS && (*info.theMap)[x + 2][y + 1].type == MAPPATTERN_GRASS) return true;
    if(y + 2 < 128 && (*info.theMap)[x][y + 2].type == MAPPATTERN_GRASS && (*info.theMap)[x + 1][y + 2].type == MAPPATTERN_GRASS) return true;
    return false;
}
bool UsrAI::feasibleWater(int x, int y){
    if((*info.theMap)[x][y].type != MAPPATTERN_OCEAN || MAP[x][y] != 0) return false;
    int cnt = 0;
    for(int k = 0; k < 4; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128 && (*info.theMap)[i][j].type == MAPPATTERN_GRASS) cnt++;
    }
    return cnt >= 1;//.......
}
bool UsrAI::feasibleGrass(int x, int y, int kk){
    if((*info.theMap)[x][y].type != MAPPATTERN_GRASS || MAP[x][y] != 0) return false;
    int cnt = 0;
    for(int k = 0; k < 4; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128 && (*info.theMap)[i][j].type == MAPPATTERN_OCEAN) cnt++;
    }
    return cnt == kk;//.......
}
bool UsrAI::feasibleGrass(int x, int y){
    if((*info.theMap)[x][y].type != MAPPATTERN_GRASS || MAP[x][y] != 0) return false;
    int cnt = 0;
    for(int k = 0; k < 4; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128 && (*info.theMap)[i][j].type == MAPPATTERN_OCEAN) cnt++;
    }
    return cnt >= 1;
}
bool UsrAI::feasibleArea(int x, int y){
    if((*info.theMap)[x][y].type != MAPPATTERN_GRASS || MAP[x][y] != 0) return false;
    int cnt = 0;
    for(int k = 0; k < 8; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128){
            if((*info.theMap)[i][j].type == MAPPATTERN_UNKNOWN) cnt++;
            if((*info.theMap)[i][j].type == MAPPATTERN_OCEAN || MAP[i][j] != 0) return false;
        }
    }
    return cnt >= 3;
}
bool UsrAI::feasibleHeight(int x, int y){
    int height = Map[x][y];
    for(int k = 0; k < 4; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i < 0 || i >= 128 || j < 0 || j >= 128 || (*info.theMap)[i][j].type != MAPPATTERN_GRASS || Map[i][j] != height) return false;
    }
    return true;
}
bool UsrAI::feasibleSea(int x, int y){
    if((*info.theMap)[x][y].type != MAPPATTERN_OCEAN || MAP[x][y] != 0) return false;
    int nx, ny;
    findGrassSpace(x, y, nx, ny);
    if(distance(x, y, nx, ny) >= 6 || newContinent.count({nx, ny})) return false;
    int cnt = 0;
    for(int k = 0; k < 8; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128){
            if((*info.theMap)[i][j].type == MAPPATTERN_UNKNOWN) cnt++;
        }
    }
    return cnt >= 3;
}
bool UsrAI::feasibleShore(int x, int y){
    if((*info.theMap)[x][y].type != MAPPATTERN_GRASS || MAP[x][y] != 0) return false;
    int cnt = 0;
    for(int k = 0; k < 4; k++){
        int i = x + dx[k];
        int j = y + dy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128 && (*info.theMap)[i][j].type == MAPPATTERN_OCEAN) cnt++;
    }
    return cnt >= 1;//.......
}
bool UsrAI::feasibleGold(tagResource& gold, int& cnt){
    if(findHumanWorkingOnResource(gold.SN) >= 1) return false;
    cnt = 0;
    int x = gold.BlockDR, y = gold.BlockUR;
    for(int k = 0; k < 12; k++){
        int i = x + ddx[k];
        int j = y + ddy[k];
        if(i >= 0 && i < 128 && j >= 0 && j < 128){
            if(MAP[i][j] != RESOURCE_GOLD + 'A') cnt++;
        }

    }
    if(cnt > 10) cnt = 2;
    return cnt >= 2 && cnt <= 10;
}
void UsrAI::findWaterSpace(int center_x, int center_y, int& x, int& y, int k){
    int min_distance = INT_MAX;
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if(feasibleWater(i, j)){
                int cur_distance = abs(center_x - i) + abs(center_y - j);
                if(cur_distance < min_distance && cur_distance > k){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
}
void UsrAI::findWaterSpace(tagFarmer& idleFarmer, int& x, int& y){
    int min_distance = INT_MAX;
    for(int i = 0; i < 127; i++){
        for(int j = 0; j < 127; j++){
            if(feasibleWaterSpace(i, j)){
                int cur_distance = abs(idleFarmer.BlockDR - i) + abs(idleFarmer.BlockUR - j);
                if(cur_distance < min_distance){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
}
void UsrAI::findWaterSpace(tagResource& resource, int& x, int& y){
    int min_distance = INT_MAX;
    for(int i = 0; i < 127; i++){
        for(int j = 0; j < 127; j++){
            if(feasibleWaterSpace(i, j)){
                int cur_distance = abs(resource.BlockDR - i) + abs(resource.BlockUR - j);
                if(cur_distance < min_distance){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
}
void UsrAI::findGrassSpace(int center_x, int center_y, int& x, int& y, int k, int kk){
    int min_distance = INT_MAX;
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if(feasibleGrass(i, j, kk)){
                int cur_distance = abs(center_x - i) + abs(center_y - j);
                if(cur_distance < min_distance && cur_distance > k){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
}
bool UsrAI::findGrassSpace(int center_x, int center_y, int& x, int& y){
    int min_distance = INT_MAX;
    for(int i = 0; i < 128; i++){
        for(int j = 0; j < 128; j++){
            if(feasibleGrass(i, j)){
                int cur_distance = abs(center_x - i) + abs(center_y - j);
                if(cur_distance < min_distance){
                    x = i, y = j;
                    min_distance = cur_distance;
                }
            }
        }
    }
    return min_distance != INT_MAX;
}
void UsrAI::findShore(int center_x, int center_y, int& x, int& y){
    int min_distance = INT_MAX;
    for(pair<int, int> cur : newSea){
        int i = cur.first, j = cur.second;
        if(!feasibleWater(i, j)) continue;
        int cur_distance = abs(center_x - i) + abs(center_y - j);
        if(cur_distance < min_distance){
            x = i, y = j;
            min_distance = cur_distance;
        }
     }
}
bool UsrAI::buildDock(){
    if(dock_N >= 2) return false;
    if(info.Wood < BUILD_DOCK_WOOD) return false;
    tagFarmer idleFarmer;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    int x, y;
    tagResource fishery;
    findNearbyResource(center_x, center_y, fishery, RESOURCE_FISH, 0);
    findWaterSpace(fishery, x, y);
    tagBuilding dock;
    if(findBuilding(center_x, center_y, BUILDING_DOCK, dock) && distance(x, y, dock.BlockDR, dock.BlockUR) < 8) return false;
    HumanBuild(idleFarmer.SN, BUILDING_DOCK, x, y);
    return true;
}
bool UsrAI::buildDock(tagResource& resource){
    if(info.Wood < BUILD_DOCK_WOOD) return false;
    tagFarmer idleFarmer;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    int x, y;
    findWaterSpace(resource, x, y);
    HumanBuild(idleFarmer.SN, BUILDING_DOCK, x, y);
    return true;
}
bool UsrAI::buildHouse(){
    if(info.Meat < 100) return false;
    if(stage == 0 && house_N >= 8) return false;
    if(stage > 0 && house_N >= 12) return false;
    tagFarmer idleFarmer;
    int x, y;
    if(info.Wood < BUILD_HOUSE_WOOD) return false;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    if(stage == 0){
        findAvailableSpace(center_x, center_y, x, y, 4, 7);
    }else{
        tagBuilding wareHouse;
        findBuilding(center_x, center_y, BUILDING_STOCK, wareHouse);
        findAvailableSpace(wareHouse.BlockDR, wareHouse.BlockUR, x, y, 3, 6);
    }
    HumanBuild(idleFarmer.SN, BUILDING_HOME, x, y);
    return true;
}
bool UsrAI::buildWareHouse(int center_x, int center_y, int op){//有必要的话可以写个重载
    tagFarmer idleFarmer;
    int x, y;
    if(info.Wood < BUILD_STOCK_WOOD) return false;
    if(findAvailableSpace(center_x, center_y, x, y, 3, 6) == false) return false;
    if(op == 0){
        if(findIdleFarmer(idleFarmer, 0) == false) return false;
    }else{
        if(findIdleFarmer(idleFarmer) == false) return false;
        if(!newContinent.count({x, y})){
            double x, y;
            if(findNearbyUnknown(idleFarmer.BlockDR, idleFarmer.BlockUR, x, y) == false) return false;
            HumanMove(idleFarmer.SN, x * size + 15, y * size + 15);
            return true;
        }
    }
    HumanBuild(idleFarmer.SN, BUILDING_STOCK, x, y);
    return true;
}
bool UsrAI::buildGranary(){
    tagFarmer idleFarmer;
    if(granary_N >= 1){
        tagBuilding granary;
        findBuilding(center_x, center_y, BUILDING_GRANARY, granary);
        if(granary.Percent == 100 || findHumanWorkingOnSomething(granary.SN) >= 2) return false;
        if(findIdleFarmer(idleFarmer, 0) == false) return false;
        HumanAction(idleFarmer.SN, granary.SN);
        return true;
    }
    if(info.Wood < BUILD_GRANARY_WOOD) return false;
    int x, y;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    findAvailableSpace(center_x, center_y, x, y, 3, 12);
    HumanBuild(idleFarmer.SN, BUILDING_GRANARY, x, y);
    return true;
}
bool UsrAI::buildMarket(){
    tagBuilding granary;
    tagFarmer idleFarmer;
    if(findBuilding(center_x, center_y, BUILDING_GRANARY, granary) == false || granary.Percent < 100) return false;
    if(market_N >= 1){
        tagBuilding market;
        findBuilding(center_x, center_y, BUILDING_MARKET, market);
        if(market.Percent == 100 || findHumanWorkingOnSomething(market.SN) >= 2) return false;
        if(findIdleFarmer(idleFarmer, 0) == false) return false;
        HumanAction(idleFarmer.SN, market.SN);
        return true;
    }
    if(info.Wood < BUILD_MARKET_WOOD) return false;
    int x, y;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    findAvailableSpace(center_x, center_y, x, y, 3, 12);
    HumanBuild(idleFarmer.SN, BUILDING_MARKET, x, y);
    return true;
}
bool UsrAI::buildArmyCamp(){
    tagFarmer idleFarmer;
    if(armyCamp_N >= 1){
        tagBuilding armyCamp;
        findBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp);
        if(armyCamp.Percent == 100 || findHumanWorkingOnSomething(armyCamp.SN) >= 2) return false;
        if(findIdleFarmer(idleFarmer, 0) == false) return false;
        HumanAction(idleFarmer.SN, armyCamp.SN);
        return true;
    }
    if(info.Wood < BUILD_ARMYCAMP_WOOD) return false;
    int x, y;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    findAvailableSpace(center_x, center_y, x, y, 3, 20);
    HumanBuild(idleFarmer.SN, BUILDING_ARMYCAMP, x, y);
    return true;
}
bool UsrAI::buildStable(int center_x, int center_y){
    tagBuilding armyCamp;
    tagFarmer idleFarmer;
    if(findBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp) == false || armyCamp.Percent < 100) return false;
    if(findFirst && !findNewEnemy){
        if(scout_N >= 1) return false;
        if(stable_N >= 1) return false;
    }
    if(stable_N >= 2) return false;
    if(info.Wood < BUILD_STABLE_WOOD) return false;
    int x, y;
    if(findIdleFarmer(idleFarmer) == false) return false;
    findAvailableSpace(center_x, center_y, x, y, 3, 0);
    if(!newContinent.count({x, y})) return false;
    HumanBuild(idleFarmer.SN, BUILDING_STABLE, x, y);
    return true;
}
bool UsrAI::buildRange(){
    tagBuilding armyCamp;
    tagFarmer idleFarmer;
    if(findBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp) == false || armyCamp.Percent < 100) return false;
    if(range_N >= 2) return false;
    if(info.Wood < BUILD_RANGE_WOOD) return false;
    int x, y;
    if(findIdleFarmer(idleFarmer) == false) return false;
    findAvailableSpace(armyCamp.BlockDR + 1, armyCamp.BlockUR + 1, x, y, 3, 6);
    if(!newContinent.count({x, y})) return false;
    HumanBuild(idleFarmer.SN, BUILDING_RANGE, x, y);
    return true;
}
bool UsrAI::buildFarm(){
    tagBuilding market;
    if(findBuilding(center_x, center_y, BUILDING_MARKET, market) == false || market.Percent < 100) return false;
    if(farm_N >= 3 || info.Meat >= 500) return false;
    if(info.Wood < BUILD_FARM_WOOD) return false;
    tagFarmer idleFarmer;
    int x, y;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    tagBuilding granary;
    findBuilding(center_x, center_y, BUILDING_GRANARY, granary);
    findAvailableSpace(granary.BlockDR, granary.BlockUR, x, y, 3, 7);
    HumanBuild(idleFarmer.SN, BUILDING_FARM, x, y);
    return true;
}
bool UsrAI::buildArrowTower(){
    tagBuilding armyCamp;
    tagFarmer idleFarmer;
    if(findBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp) == false || armyCamp.Percent < 100) return false;
    if(arrowTower_N >= 3) return false;
    if(info.Stone < BUILD_ARROWTOWER_STONE) return false;
    int x, y;
    if(findIdleFarmer(idleFarmer) == false) return false;
    findAvailableSpace(armyCamp.BlockDR + 1, armyCamp.BlockUR + 1, x, y, 2, 6);
    if(!newContinent.count({x, y})) return false;
    HumanBuild(idleFarmer.SN, BUILDING_ARROWTOWER, x, y);
    return true;
}
bool UsrAI::upgradeCutting(){
    if(is_upgradeCutting) return false;
    if(info.Meat < BUILDING_MARKET_WOOD_UPGRADE_FOOD) return false;
    if(info.Wood < BUILDING_MARKET_WOOD_UPGRADE_WOOD) return false;
    tagBuilding market;
    if(findNearbyBuilding(center_x, center_y, BUILDING_MARKET, market) == false) return false;
    BuildingAction(market.SN, BUILDING_MARKET_WOOD_UPGRADE);
    DebugText("已升级伐木技术");
    is_upgradeCutting = true;
    return true;
}
bool UsrAI::upgradeStone(){
    if(is_upgradeStone) return false;
    if(info.Meat < BUILDING_MARKET_STONE_UPGRADE_FOOD) return false;
    if(info.Stone < BUILDING_MARKET_STONE_UPGRADE_STONE) return false;
    tagBuilding market;
    if(findNearbyBuilding(center_x, center_y, BUILDING_MARKET, market) == false) return false;
    BuildingAction(market.SN, BUILDING_MARKET_STONE_UPGRADE);
    DebugText("已升级采石技术");
    is_upgradeStone = true;
    return true;
}
bool UsrAI::upgradeGold(){
    if(is_upgradeGold) return false;
    if(info.Meat < BUILDING_MARKET_GOLD_UPGRADE_FOOD) return false;
    if(info.Wood < BUILDING_MARKET_GOLD_UPGRADE_WOOD) return false;
    tagBuilding market;
    if(findNearbyBuilding(center_x, center_y, BUILDING_MARKET, market) == false) return false;
    BuildingAction(market.SN, BUILDING_MARKET_GOLD_UPGRADE);
    DebugText("已升级采金技术");
    is_upgradeGold = true;
    return true;
}
bool UsrAI::upgradeClubMan(){
    if(is_upgradeClubMan) return false;
    if(info.Meat < BUILDING_ARMYCAMP_UPGRADE_CLUBMAN_FOOD) return false;
    tagBuilding armyCamp;
    if(findNearbyBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp) == false) return false;
    BuildingAction(armyCamp.SN, BUILDING_ARMYCAMP_UPGRADE_CLUBMAN);
    DebugText("已升级为斧头兵");
    is_upgradeClubMan = true;
    return true;
}
bool UsrAI::produceFishingBoat(){
    if(stage > 0 && ship_N < 8) return false;
    if(stage == 2 && produceBoat()) return true;
    if(stage == 2 && boat_N < 1) return false;
    if(stage < 2 && findFirstShip) return false;
    if(fishingBoat_N >= 6) return false;
    if(info.farmers.size() >= info.Human_MaxNum) return false;
    if(info.Wood < BUILDING_DOCK_CREATE_SAILING_WOOD) return false;
    tagBuilding dock;
    if(findNearbyBuilding(center_x, center_y, BUILDING_DOCK, dock) == false) return false;
    BuildingAction(dock.SN, BUILDING_DOCK_CREATE_SAILING);
    return true;
}
bool UsrAI::produceFarmer(){
    if(stage == 0 && farmer_N >= 10) return false;
    if(stage > 0 && farmer_N >= 20 && farmer_cnt >= 10) return false;
    if(info.farmers.size() + info.armies.size() >= info.Human_MaxNum) return false;
    if(info.Meat < BUILDING_CENTER_CREATEFARMER_FOOD) return false;
    tagBuilding center;
    if(findNearbyBuilding(0, 0, BUILDING_CENTER, center) == false) return false;
    BuildingAction(center.SN, BUILDING_CENTER_CREATEFARMER);
    farmer_N++;
    return true;
}
bool UsrAI::produceShip(){
    if(ship_N >= 8) return false;
    if(stage == 2 && (produceBoat() || buildHouse()) || buildArmyCamp()) return true;
    if(stage == 2 && boat_N < 1) return false;
    if(info.farmers.size() + info.armies.size() >= info.Human_MaxNum) return false;
    if(info.Wood < BUILDING_DOCK_CREATE_SHIP_WOOD) return false;
    tagBuilding dock;
    if(findNearbyBuilding(center_x, center_y, BUILDING_DOCK, dock) == false) return false;
    BuildingAction(dock.SN, BUILDING_DOCK_CREATE_SHIP);
    return true;
}
bool UsrAI::produceBoat(){
    if(boat_N >= 1) return false; //假设不会被摧毁
    if(info.farmers.size() + info.armies.size() >= info.Human_MaxNum) return false;
    if(info.Wood < BUILDING_DOCK_CREATE_WOOD_BOAT_WOOD) return false;
    tagBuilding dock;
    if(findNearbyBuilding(center_x, center_y, BUILDING_DOCK, dock) == false) return false;
    BuildingAction(dock.SN, BUILDING_DOCK_CREATE_WOOD_BOAT);
    boat_N++;
    return true;
}
bool UsrAI::produceClubMan(){
    if(clubMan_N >= 8) return false;
    if(info.farmers.size() + info.armies.size() >= info.Human_MaxNum) return false;
    if(info.Meat < BUILDING_ARMYCAMP_CREATE_CLUBMAN_FOOD) return false;
    tagBuilding armyCamp;
    if(findNearbyBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp) == false) return false;
    BuildingAction(armyCamp.SN, BUILDING_ARMYCAMP_CREATE_CLUBMAN);
    return true;
}
bool UsrAI::produceScout(){
    if(findFirst && !findNewEnemy && scout_N >= 3) return false;
    if(scout_N >= 6) return false;
    if(info.farmers.size() + info.armies.size() >= info.Human_MaxNum) return false;
    if(info.Meat < BUILDING_STABLE_CREATE_SCOUT_FOOD) return false;
    tagBuilding stable;
    if(findNearbyBuilding(center_x, center_y, BUILDING_STABLE, stable) == false) return false;
    BuildingAction(stable.SN, BUILDING_STABLE_CREATE_SCOUT);
    return true;
}
bool UsrAI::produceBowMan(){
    if(bowMan_N >= 8) return false;
    if(info.farmers.size() + info.armies.size() >= info.Human_MaxNum) return false;
    if(info.Meat < BUILDING_RANGE_CREATE_BOWMAN_FOOD) return false;
    if(info.Wood < BUILDING_RANGE_CREATE_BOWMAN_WOOD) return false;
    tagBuilding range;
    if(findNearbyBuilding(center_x, center_y, BUILDING_RANGE, range) == false) return false;
    BuildingAction(range.SN, BUILDING_RANGE_CREATE_BOWMAN);
    return true;
}
bool UsrAI::upgradeFarm(){
    if(is_upgradeFarm) return false;
    if(info.Meat < BUILDING_MARKET_FARM_UPGRADE_FOOD) return false;
    if(info.Wood < BUILDING_MARKET_FARM_UPGRADE_WOOD) return false;
    tagBuilding market;
    if(findNearbyBuilding(center_x, center_y, BUILDING_MARKET, market) == false) return false;
    BuildingAction(market.SN, BUILDING_MARKET_FARM_UPGRADE);
    DebugText("已升级农场技术");
    is_upgradeFarm = true;
    return true;
}
bool UsrAI::upgradeTool(){
    if(is_upgradeTool) return false;
    if(info.Meat < BUILDING_STOCK_UPGRADE_USETOOL_FOOD) return false;
    tagBuilding wareHouse;
    if(findNearbyBuilding(center_x, center_y, BUILDING_STOCK, wareHouse) == false) return false;
    BuildingAction(wareHouse.SN, BUILDING_STOCK_UPGRADE_USETOOL);
    DebugText("已升级工具技术");
    is_upgradeTool = true;
    return true;
}
bool UsrAI::upgradeInfantry(){
    if(is_upgradeInfantry) return false;
    if(info.Meat < BUILDING_STOCK_UPGRADE_DEFENSE_INFANTRY_FOOD) return false;
    tagBuilding wareHouse;
    if(findNearbyBuilding(center_x, center_y, BUILDING_STOCK, wareHouse) == false) return false;
    BuildingAction(wareHouse.SN, BUILDING_STOCK_UPGRADE_DEFENSE_INFANTRY);
    DebugText("已升级步兵护甲");
    is_upgradeInfantry = true;
    return true;
}
bool UsrAI::upgradeArcher(){
    if(is_upgradeArcher) return false;
    if(info.Meat < BUILDING_STOCK_UPGRADE_DEFENSE_ARCHER_FOOD) return false;
    tagBuilding wareHouse;
    if(findNearbyBuilding(center_x, center_y, BUILDING_STOCK, wareHouse) == false) return false;
    BuildingAction(wareHouse.SN, BUILDING_STOCK_UPGRADE_DEFENSE_ARCHER);
    DebugText("已升级弓兵护甲");
    is_upgradeArcher = true;
    return true;
}
bool UsrAI::upgradeRider(){
    if(is_upgradeRider) return false;
    if(info.Meat < BUILDING_STOCK_UPGRADE_DEFENSE_RIDER_FOOD) return false;
    tagBuilding wareHouse;
    if(findNearbyBuilding(center_x, center_y, BUILDING_STOCK, wareHouse) == false) return false;
    BuildingAction(wareHouse.SN, BUILDING_STOCK_UPGRADE_DEFENSE_RIDER);
    DebugText("已升级骑兵护甲");
    is_upgradeRider = true;
    return true;
}
bool UsrAI::researchArrowTower(){
    if(is_researchArrowTower) return false;
    if(info.Meat < BUILDING_GRANARY_ARROWTOWER_FOOD) return false;
    tagBuilding granary;
    if(findNearbyBuilding(center_x, center_y, BUILDING_GRANARY, granary) == false) return false;
    BuildingAction(granary.SN, BUILDING_GRANARY_ARROWTOWER);
    DebugText("已研发箭塔");
    is_researchArrowTower = true;
    return true;
}
vector<int> twoFarmers[2];
bool UsrAI::hunting(int op){
    tagResource gazelle;
    tagBuilding wareHouse;
    if(op == 1){
       tagFarmer idleFarmer;
       if(findIdleFarmer(idleFarmer) == false) return false;
       if(findNearbyLivingResource(idleFarmer.BlockDR, idleFarmer.BlockUR, gazelle, RESOURCE_GAZELLE)){
           HumanAction(idleFarmer.SN, gazelle.SN);
           return true;
       }
       if(findNearbyResource(idleFarmer.BlockDR, idleFarmer.BlockUR, gazelle, RESOURCE_GAZELLE, 0)){
           tagBuilding stock;
           findNearbyBuilding(gazelle.BlockDR, gazelle.BlockUR, BUILDING_STOCK, stock);
           if(distance(gazelle.BlockDR, gazelle.BlockUR, stock.BlockDR, stock.BlockUR) > 10){
               if(buildWareHouse(gazelle.BlockDR, gazelle.BlockUR, 1)) return true;
               return false;
           }
           HumanAction(idleFarmer.SN, gazelle.SN);
           return true;
       }
       return false;
    }
    if(stage == 0 && wareHouse_N == 0){
        if(findNearbyResource(center_x, center_y, gazelle, RESOURCE_GAZELLE, 0) == false) return false; //有可能找不到，或者找到了但过不去
        if(buildWareHouse(gazelle.BlockDR, gazelle.BlockUR, op)) return true;
        return false;
    }
    if(twoFarmers[0].size() < 2){
        if(findSomeFarmers(twoFarmers[0], 2, 0, op) == false) return false;
    }
    tagFarmer farmer1 = farmers[twoFarmers[0][0]];
    tagFarmer farmer2 = farmers[twoFarmers[0][1]];
    if(stage == 0 && findNearbyLivingResource(farmer1.BlockDR, farmer1.BlockUR, gazelle, RESOURCE_GAZELLE)){
        if(farmer1.NowState == HUMAN_STATE_IDLE || resources[farmer1.WorkObjectSN].Blood == 0){
            HumanAction(farmer1.SN, gazelle.SN);
            HumanAction(farmer2.SN, gazelle.SN);
            return true;
        }
        return false;
    }
    tagResource gazelle0;
    double cur_distance = INT_MIN;
    findBuilding(farmer1.BlockDR, farmer1.BlockUR, BUILDING_DOCK, wareHouse);
    if(findNearbyResource(wareHouse.BlockDR, wareHouse.BlockUR, gazelle, RESOURCE_GAZELLE, 0)){
        if(newContinent.count({gazelle.BlockDR, gazelle.BlockUR}) != op) return false;
        if(farmer1.NowState == HUMAN_STATE_WORKING){
            gazelle0 = resources[farmer1.WorkObjectSN];
            cur_distance = pow(wareHouse.BlockDR - gazelle0.BlockDR, 2) + pow(wareHouse.BlockUR - gazelle0.BlockUR, 2);
        }
        double distance = pow(wareHouse.BlockDR - gazelle.BlockDR, 2) + pow(wareHouse.BlockUR - gazelle.BlockUR, 2);
        if(farmer1.NowState == HUMAN_STATE_IDLE || distance < cur_distance){
            HumanAction(farmer1.SN, gazelle.SN);
            HumanAction(farmer2.SN, gazelle.SN);
            return true;
        }
    }
    return false;
}
bool UsrAI::hunting(){
    tagResource elephant;
    tagBuilding stock;
    if(findNearbyResource(center_x, center_y, elephant, RESOURCE_ELEPHANT, 0) == false) return false;
    if(newContinent.count({elephant.BlockDR, elephant.BlockUR})) return false;
    findBuilding(elephant.BlockDR, elephant.BlockUR, BUILDING_STOCK, stock);
    if(distance(elephant.BlockDR, elephant.BlockUR, stock.BlockDR, stock.BlockUR) < 10){
        buildWareHouse(elephant.BlockDR, elephant.BlockUR, 0);
    }
    if(twoFarmers[1].size() < 2){
        if(findSomeFarmers(twoFarmers[1], 2, 0, 0) == false) return false;
    }
    tagFarmer farmer1 = farmers[twoFarmers[1][0]];
    tagFarmer farmer2 = farmers[twoFarmers[1][1]];
    if(findNearbyLivingResource(farmer1.BlockDR, farmer1.BlockUR, elephant, RESOURCE_ELEPHANT)){
        if(farmer1.NowState == HUMAN_STATE_IDLE || resources[farmer1.WorkObjectSN].Blood == 0){
            HumanAction(farmer1.SN, elephant.SN);
            HumanAction(farmer2.SN, elephant.SN);
            return true;
        }
        return false;
    }
    tagResource elephant0;
    double cur_distance = INT_MIN;
    findBuilding(farmer1.BlockDR, farmer1.BlockUR, BUILDING_DOCK, stock);
    if(farmer1.NowState == HUMAN_STATE_WORKING){
        elephant0 = resources[farmer1.WorkObjectSN];
        cur_distance = pow(stock.BlockDR - elephant0.BlockDR, 2) + pow(stock.BlockUR - elephant0.BlockUR, 2);
    }
    double distance = pow(stock.BlockDR - elephant.BlockDR, 2) + pow(stock.BlockUR - elephant.BlockUR, 2);
    if(farmer1.NowState == HUMAN_STATE_IDLE || distance < cur_distance){
        HumanAction(farmer1.SN, elephant.SN);
        HumanAction(farmer2.SN, elephant.SN);
        return true;
    }
    return false;
}
bool UsrAI::fishing(){
    tagFarmer idleFishingBoat;
    tagResource fishery;
    tagBuilding fishingBoat;
    if(findIdleFarmer(idleFishingBoat, 2) == false){
        bool ok = false;
        for(auto& farmer : info.farmers){
            if(farmer.FarmerSort == 2){
                findBuilding(farmer.BlockDR, farmer.BlockUR, BUILDING_DOCK, fishingBoat);
                if(findNearbyResource(fishingBoat.BlockDR, fishingBoat.BlockUR, fishery, RESOURCE_FISH, 0) == false) return false;
                if(farmer.WorkObjectSN != fishery.SN){
                    HumanAction(farmer.SN, fishery.SN);
                    ok = true;
                }
            }
        }
        return ok;
    }
    findBuilding(idleFishingBoat.BlockDR, idleFishingBoat.BlockUR, BUILDING_DOCK, fishingBoat);
    if(findNearbyResource(fishingBoat.BlockDR, fishingBoat.BlockUR, fishery, RESOURCE_FISH, 0)){
        int cur_distance = abs(fishingBoat.BlockDR - fishery.BlockDR) + abs(fishingBoat.BlockUR - fishery.BlockUR);
        if(cur_distance > 20){
            if(dock_N <= 2){
                if(buildDock(fishery)) return true;
            }
        }
        HumanAction(idleFishingBoat.SN, fishery.SN);
    }else{
        int x, y;
        if(findNearbyUnknownSea(idleFishingBoat.BlockDR, idleFishingBoat.BlockUR, x, y) == false) return false;
        HumanMove(idleFishingBoat.SN, x * size + 15, y * size + 15);
        return true;
    }
}
bool UsrAI::exploring(){
    tagArmy idleShip;
    int x, y, k;
    bool ok = false;
    if(findEnemy){
        tagArmy enemy;
        bool okk = false;
        if(findNearbyEnemy(center_x, center_y, enemy, AT_SHIP)) okk = true;
        for(auto& army : info.armies){
            if(army.Sort == AT_SHIP){
                if((army.NowState == HUMAN_STATE_WALKING || army.NowState == HUMAN_STATE_IDLE) && okk){
                    HumanAction(army.SN, enemy.SN);
                    ok = true;
                    continue;
                }
                if(okk) continue;
                if((army.NowState == HUMAN_STATE_ATTACKING || army.NowState == HUMAN_STATE_IDLE)
                        && findNewShore && distance(army.BlockDR, army.BlockUR, shore_x, shore_y) > 10){
                    HumanMove(army.SN, (shore_x + 0.5) * size, (shore_y + 0.5) * size);
                    ok = true;
                    continue;
                }
                if(findNewShore && distance(army.BlockDR, army.BlockUR, shore_x, shore_y) > 10) continue;
                findNearbyEnemy(army.BlockDR, army.BlockUR, enemy);
                findShore(enemy.BlockDR, enemy.BlockUR, x, y);
                if((army.NowState == HUMAN_STATE_ATTACKING || army.NowState == HUMAN_STATE_IDLE) && distance(army.BlockDR, army.BlockUR, x, y) > 5){
                    HumanMove(army.SN, (x + 0.5) * size, (y + 0.5) * size);
                    ok = true;
                    continue;
                }
                if(distance(army.BlockDR, army.BlockUR, x, y) > 5) continue;
                if((army.NowState == HUMAN_STATE_WALKING || army.NowState == HUMAN_STATE_IDLE) && distance(army.BlockDR, army.BlockUR, enemy.BlockDR, enemy.BlockUR) < 10){
                    HumanAction(army.SN, enemy.SN);
                    ok = true;
                }
            }
        }
        return false;
    }else if(stage == 1){
        if(findNewContinent){
            stage++;
            return false;
        }
        tagBuilding market;
        if(ship_N < 8 || findBuilding(center_x, center_y, BUILDING_MARKET, market) == false) return false;
        if(findIdleArmy(idleShip, AT_SHIP) == false) return false;
        if(findNearbyArea(idleShip.BlockDR, idleShip.BlockUR, x, y, k) == false) return false;
        for(auto& army : info.armies){
            if(army.Sort == AT_SHIP){
                if(army.NowState == HUMAN_STATE_IDLE){
                    ships[army.SN] = k;
                    HumanMove(army.SN, x * size, y * size);
                }else if(army.NowState == HUMAN_STATE_WALKING){
                    if(is_visited[ships[army.SN]]){
                        ships[army.SN] = k;
                        HumanMove(army.SN, x * size, y * size);
                    }
                }
            }
        }
    }else if(findNewContinent){
        //去最近的大陆
        int x, y;
        for(auto& army : info.armies){
            if(army.Sort == AT_SHIP && army.NowState == HUMAN_STATE_IDLE){
                findShore(army.BlockDR, army.BlockUR, x, y);
                if(distance(army.BlockDR, army.BlockUR, x, y) < 5) continue;
                ok = true;
                HumanMove(army.SN, (x + 0.5) * size, (y + 0.5) * size);
            }
        }
//        return ok;
    }
    return false;
}
bool UsrAI::working(){
    if(buildHouse()) return true;
    if(produceFarmer()) return true;
    if(buildFarm()) return true;
    if(upgradeTool()) return true;
//    if(upgradeInfantry()) return true;
    if(upgradeArcher()) return true;
    if(upgradeRider()) return true;
    if(upgradeGold()) return true;
    if(buildArmyCamp()) return true;
    return false;
}
bool UsrAI::starting(){
    tagFarmer fullBoat;
    if(findFullBoat(fullBoat) == false) return false;
    farmerOnBoat[fullBoat.SN] = fullBoat.Resource;
    boatBack[fullBoat.SN] = false;
    double x, y;
    if(findNearbyContinent(fullBoat.BlockDR, fullBoat.BlockUR, x, y) == false) return false;
    if(boatMove[fullBoat.SN] == false){
        target_x = x, target_y = y;
        HumanMove(fullBoat.SN, (x + 0.5) * size, (y + 0.5) * size);
        boatMove[fullBoat.SN] = true;
        return true;
    }
    return false;
}
bool UsrAI::escaping(){
    bool ok = false;
    tagBuilding armyCamp;
    if(findBuilding(center_x, center_y, BUILDING_ARMYCAMP, armyCamp) == false) return false;
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && newContinent.count({farmer.BlockDR, farmer.BlockUR}) && (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WORKING)){
            int x, y;
            findGrassSpace(armyCamp.BlockDR, armyCamp.BlockUR, x, y, 0, 1);
            if(distance(farmer.BlockDR, farmer.BlockUR, x, y) < 5) continue;
            ok = true;
            HumanMove(farmer.SN, x * size + 15, y * size + 15);
        }
    }
//    return ok;
    return false;
}
bool UsrAI::atacking(){
    tagArmy enemy;
    tagBuilding enemyBuilding;
    bool ok = false;
    for(auto& army : info.armies){
        if(findScout && army.Sort != AT_SHIP && (army.NowState == HUMAN_STATE_ATTACKING || army.NowState == HUMAN_STATE_IDLE)
                && distance(army.BlockDR, army.BlockUR, grass_x, grass_y) > 5 && enemy_cnt > scout_N){
            HumanMove(army.SN, (grass_x + 0.5) * size, (grass_y + 0.5) * size);
            ok = true;
            continue;
        }
        if(findScout && enemy_cnt > scout_N && distance(army.BlockDR, army.BlockUR, grass_x, grass_y) > 5) continue;
        if(army.Sort != AT_SHIP && (army.NowState == HUMAN_STATE_WALKING || army.NowState == HUMAN_STATE_IDLE)){
            if(findNearbyEnemy(army.BlockDR, army.BlockUR, enemy, AT_BOWMAN)){
                 HumanAction(army.SN, enemy.SN);
            }else if(findNearbyEnemy(army.BlockDR, army.BlockUR, enemy)){
                 HumanAction(army.SN, enemy.SN);
            }else if(findNearbyEnemyBuilding(army.BlockDR, army.BlockUR, enemyBuilding)){
                 HumanAction(army.SN, enemyBuilding.SN);
            }
            ok = true;
        }
    }
    for(auto& farmer : info.farmers){
        if(farmer.FarmerSort == 0 && newContinent.count({farmer.BlockDR, farmer.BlockUR}) &&
                (farmer.NowState == HUMAN_STATE_IDLE || farmer.NowState == HUMAN_STATE_WORKING || farmer.NowState == HUMAN_STATE_WALKING)){
            if(findNearbyEnemy(farmer.BlockDR, farmer.BlockUR, enemy, AT_BOWMAN)){
                 HumanAction(farmer.SN, enemy.SN);
            }else if(findNearbyEnemy(farmer.BlockDR, farmer.BlockUR, enemy)){
                 HumanAction(farmer.SN, enemy.SN);
            }
        }
    }
    return false;
}
bool UsrAI::moving(){
   return false;
}
bool UsrAI::researching(){
    double x, y;
    tagArmy scout;
    bool ok = false;
    bool okk = false;
    for(auto& army : info.armies){
        if(army.Sort == AT_SCOUT){
            if(army.NowState == HUMAN_STATE_IDLE || army.NowState == HUMAN_STATE_WALKING && feasibleGrass(army.BlockDR, army.BlockUR, 1)){
                scout = army;
                ok = true;
            }
        }
    }
    if(!ok) return okk;
    if(findNearbyUnknown(scout.BlockDR, scout.BlockUR, x, y) == false) return false;
    HumanMove(scout.SN, x * size + 15, y * size + 15);
    return false;
}
bool UsrAI::helping(){
    tagFarmer idleFarmer;
    if(findIdleFarmer(idleFarmer) == false) return false;
    for(auto& building : info.buildings){
        if(building.Percent < 100 && newContinent.count({building.BlockDR, building.BlockUR}) && findHumanWorkingOnSomething(building.SN) < 3){
            HumanAction(idleFarmer.SN, building.SN);
            return true;
        }
    }
    return false;
}
bool UsrAI::callFarmer(){
    tagFarmer idleBoat;
    if(findIdleBoat(idleBoat) == false) return false;
    boatMove[idleBoat.SN] = false;
    int x, y;
    if(boats.find(idleBoat.SN) == boats.end()){
        findGrassSpace(center_x, center_y, x, y, 5, 1);
        boats[idleBoat.SN] = {x, y};
        HumanMove(idleBoat.SN, x * size, y * size);
        return true;
    }
    x = boats[idleBoat.SN].first;
    y = boats[idleBoat.SN].second;
    if(boatFirstMove[idleBoat.SN] == false){
        HumanMove(idleBoat.SN, x * size, y * size);
        boatFirstMove[idleBoat.SN] = true;
        return true;
    }
    if(boatBack[idleBoat.SN] == false && distance(idleBoat.BlockDR, idleBoat.BlockUR, x, y) > 20){
        HumanMove(idleBoat.SN, x * size, y * size);
        boatBack[idleBoat.SN] = true;
        farmerOnBoat[idleBoat.SN] = 0; //  !!!!
        return true;
    }
    if(farmerOnBoat[idleBoat.SN] >= 5 || info.Wood < 150 && wareHouse_N == 1) return false;
    tagFarmer idlefarmer;
    if(findFarmer(idlefarmer, 0) == false) return false;
    cout << farmerOnBoat[idleBoat.SN] << endl;
    HumanAction(idlefarmer.SN, idleBoat.SN);
//    farmerOnBoat[idleBoat.SN]++;
    return true;
}
bool UsrAI::cancleFarmer(){
    if(cancle_N >= 5 || farmer_cnt > 5) return false;
    tagFarmer idleFarmer;
    if(findIdleFarmer(idleFarmer, 0) == false) return false;
    HumanAction(idleFarmer.SN, idleFarmer.SN);
    cancle_N++;
    return true;
}
bool UsrAI::checkBuildings(int op){
    tagFarmer idleFarmer;
    if(op == 0){
        if(findIdleFarmer(idleFarmer, 0) == false) return false;
    }else{
        if(findIdleFarmer(idleFarmer) == false) return false;
    }
    for(auto& building : info.buildings){
        if(building.Percent < 100 && newContinent.count({building.BlockDR, building.BlockUR}) == op){
            if(findHumanWorkingOnSomething(building.SN) > 0) continue;
            HumanAction(idleFarmer.SN, building.SN);
            return true;
        }
    }
    return false;
}
void UsrAI::processData(){
    info = getInfo();
    static once_flag flag;
    call_once(flag, [this](){this->init();});
    updateMap();
    switch(stage){
    case 0:
        if(info.Meat >= 500){
            tagBuilding center;
            if(findNearbyBuilding(center_x,  center_y, BUILDING_CENTER, center) == false) return;
            BuildingAction(center.SN, BUILDING_CENTER_UPGRADE);
            stage++;
            return;
        }
        if(buildDock()) return;
        if(fishing()) return;
        if(produceFarmer()) return;
        if(hunting(0)) return;
        if(buildHouse()) return;
        if(produceFishingBoat()) return;
        if(checkBuildings(0)) return;
        cutTree(0);
        break;
    case 1:
        if(info.civilizationStage == CIVILIZATION_STONEAGE){
            if(produceFarmer()) return;
            if(buildHouse()) return;
            if(buildDock()) return;
            if(fishing()) return;
            if(hunting(0)) return;
            if(checkBuildings(0)) return;
            cutTree(0);
            return;
        }
        tagBuilding market;
        if(produceFarmer()) return;
        if(buildHouse()) return;
        if(buildDock()) return;
        if(fishing()) return;
        if(hunting(0)) return;
        if(buildGranary()) return;
        if(buildMarket()) return;
        if(upgradeCutting()) return;
        if(checkBuildings(0)) return;
        if(findBuilding(center_x, center_y, BUILDING_MARKET, market) == false){
            cutTree(0);
            return;
        }
        if(produceShip()) return;
        if(exploring()) return;
        if(ship_N < 8){
            cutTree(0);
            return;
        }
        if(working()) return;
        if(checkBuildings(0)) return;
        cutTree(0);
        break;
    case 2:
        if(produceShip()) return;
        if(produceFishingBoat()) return;
        if(exploring()) return;
        tagArmy enemy;
        if(findNearbyEnemy(center_x, center_y, enemy, AT_SHIP) == false && fishing()) return;
        if(hunting(0)) return;
        if(working()) return;
        if(house_N < 12 || armyCamp_N < 1){
            cutTree(0);
            return;
        }
        if(produceBoat()) return;
        if(callFarmer()) return;
        if(starting()) return;
        if(checkBuildings(0)) return;
        if(cutTree(0)) return;
        //登陆后
        if(produceFarmer()) return;
        if(produceScout()) return;
        if(findNewEnemy && !findNewShore && researching());
        else if(findNewEnemy && findNewShore && atacking());
        else if(!findGold && researching());
        else if(findFirst && !findNewEnemy && researching());
        else if(findGold && !findNewEnemy && !findFirst && researching());
        int x, y;
        tagFarmer idleFarmer;
        tagBuilding stock;
        if(wareHouse_N == 2){
            bool ok = false;
            for(auto& farmer : info.farmers){
                if(farmer.FarmerSort == 0 && farmer.NowState == HUMAN_STATE_WALKING && farmerMove[farmer.SN] == false){
                    findAvailableSpace(farmer.BlockDR, farmer.BlockUR, x, y, 1, 0);
                    HumanMove(farmer.SN, x * size, y * size);
                    farmerMove[farmer.SN] = true;
                    ok = true;
                }
            }
            if(ok) return;
        }
        if(findIdleFarmer(idleFarmer)){
            if(wareHouse_N == 1 && buildWareHouse(idleFarmer.BlockDR, idleFarmer.BlockUR, 1)) return;
            if(buildStable(idleFarmer.BlockDR, idleFarmer.BlockUR)) return;
            if(helping()) return;
            if(checkBuildings(1)) return;
            if(findGold && digGold()) return;
            if(cutTree(1)) return;
        }
        cout << findNewShore << " " << grass_x << " " << grass_y << endl;
        break;
    }
    return;
}
